package com.xmb.wcapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xmb.wcapi.constant.R;
import com.xmb.wcapi.entity.BaseInventory;
import com.xmb.wcapi.entity.BaseMaterial;
import com.xmb.wcapi.entity.StockNow;
import com.xmb.wcapi.mapper.BaseInventoryMapper;
import com.xmb.wcapi.mapper.BaseMaterialMapper;
import com.xmb.wcapi.mapper.StockNowMapper;
import com.xmb.wcapi.service.IBaseMaterialService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class BaseMaterialServiceImpl extends ServiceImpl<BaseMaterialMapper, BaseMaterial> implements IBaseMaterialService {

    @Autowired
    private BaseMaterialMapper baseMaterialMapper;

    @Autowired
    private BaseInventoryMapper baseInventoryMapper;

    @Autowired
    private StockNowMapper stockNowMapper;

    @Override
    public IPage<BaseMaterial> getBaseMaterialList(Integer page, Integer limit, String cusCode, String invCode, String invDef) {
        //查询顶级bom
        QueryWrapper<BaseMaterial> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotEmpty(cusCode),"cusCode",cusCode);
        wrapper.like(StringUtils.isNotEmpty(invCode),"djMaterial",invCode);
        wrapper.like(StringUtils.isNotEmpty(invDef),"typeOfMachine",invDef);
        Page<Object> objectPage = new Page<>(page, limit);
        objectPage.setSearchCount(false);
        objectPage.setOptimizeCountSql(false);
        int count = baseMaterialMapper.getBaseMaterialListCount(wrapper);
        objectPage.setTotal(count);
        IPage<BaseMaterial> re = baseMaterialMapper.getBaseMaterialList(objectPage,wrapper);
        for (BaseMaterial record : re.getRecords()) {
            if (StringUtils.isEmpty(record.getBomId())){
                record.setBomId("0");
            }
        }
        return re;
    }

    @Override
    public IPage<BaseMaterial> iosBaseList(Integer page, Integer limit, String cusCode, String invCode, String invDef) {
        //查询现在已有的料号
        List<BaseMaterial> list = list(Wrappers.lambdaQuery(BaseMaterial.class).eq(BaseMaterial::getClassType, "A"));
        IPage<BaseMaterial> materialList = new Page<>(page,limit);
        if (list.isEmpty()){
            return materialList;
        }
        materialList = getBaseMaterialList(page, limit, cusCode, invCode, invDef);
        List<String> collect = list.stream().map(BaseMaterial::getComponentId).collect(Collectors.toList());
        List<BaseMaterial> materials = materialList.getRecords().stream().filter(obj -> collect.contains(obj.getComponentId())).collect(Collectors.toList());
        materialList.setRecords(materials);
        materialList.setTotal(materials.size());
        return materialList;
    }

    @Override
    public List<String> selectBaseMaterialAllGroupSet() {
        return baseMaterialMapper.selectBaseMaterialAllGroupList();
    }

    @Override
    public List<BaseMaterial> getBaseMaterialDetailsList(String bomId, String cusCode) {
        //查询子件数据
        List<BaseMaterial> list = baseMaterialMapper.selectSon(bomId);
        List<BaseMaterial> all = new ArrayList<>();
        for (BaseMaterial material : list) {
            all.add(material);
            extractedBasePage(material,all);
        }
        //加入母件
        List<BaseMaterial> baseMaterialOne = baseMaterialMapper.getBaseMaterialOne(bomId,cusCode);
        all.addAll(baseMaterialOne);
        return all;
    }

    private void extractedBasePage(BaseMaterial material, List<BaseMaterial> list) {
        boolean mark = false;
        if (StringUtils.isNotEmpty(material.getBomId())){
            List<BaseMaterial> details = baseMaterialMapper.selectSon(material.getBomId());
            for (BaseMaterial base : details) {
                if (StringUtils.isNotEmpty(base.getBomId()) &&
                        StringUtils.isNotEmpty(base.getModifyDate()) &&
                        StringUtils.isNotEmpty(base.getVersion())
                ){
                    material = base;
                    mark = true;
                    list.add(base);
                }else
                if (StringUtils.isEmpty(base.getBomId()) &&
                        StringUtils.isEmpty(base.getModifyDate()) &&
                        StringUtils.isEmpty(base.getVersion())
                ){
                    list.add(base);
                }else
                if (StringUtils.isNotEmpty(base.getBomId()) &&
                        StringUtils.isEmpty(base.getModifyDate()) &&
                        StringUtils.isNotEmpty(base.getVersion())
                ){
                    material = base;
                    mark = true;
                    list.add(base);
                }
            }
        }
        if (mark){
            extractedBasePage(material,list);
        }
    }

    @Override
    @Transactional(rollbackForClassName = "Exception")
    public R saveBaseMaterial(List<BaseMaterial> list, BaseMaterial baseMaterial1) {
        try {
            //先查找
            List<String> collect = list.stream().map(BaseMaterial::getOpComponentId).collect(Collectors.toList());
            List<BaseMaterial> listed = new ArrayList<>();
            if (!collect.isEmpty()){
                listed = list(Wrappers.lambdaQuery(BaseMaterial.class)
                        .in(BaseMaterial::getDjMaterial,collect)
                        .eq(BaseMaterial::getAllComponentId,baseMaterial1.getAllComponentId())
                );
            }
            if (!listed.isEmpty()){
                List<String> strings = listed.stream().map(BaseMaterial::getOpComponentId).collect(Collectors.toList());
                //过滤已经存在的
                list = list.stream().filter(obj -> !strings.contains(obj.getOpComponentId())).collect(Collectors.toList());
            }
            saveBatch(list);


            //添加期初和现存量
            List<BaseMaterial> baseMaterials = baseMaterialMapper.selectList(Wrappers.lambdaQuery(BaseMaterial.class)
                    .eq(BaseMaterial::getAllComponentId, baseMaterial1.getAllComponentId())
                    .eq(BaseMaterial::getClassType,"B")
                    .eq(BaseMaterial::isChecked,true)
            );
            Set<String> strings = baseMaterials.stream().map(BaseMaterial::getDjMaterial).collect(Collectors.toSet());
            // 查询现存量
            List<StockNow> stockNows = stockNowMapper.selectList(Wrappers.lambdaQuery(StockNow.class).in(StockNow::getMaterial,strings));
            Map<String, Long> map = stockNows.stream().collect(Collectors.toMap(StockNow::getMaterial, StockNow::getMaterialSum));
            //现存量表中添加 半成品
            for (String key : strings) {
                if (null == map.get(key)){
                    StockNow stockNow = new StockNow();
                    stockNow.setTimes(new Date());
                    stockNow.setMaterial(key);
                    stockNow.setMaterialSum(0L);
                    stockNow.setCreateTime(new Date());
                    stockNowMapper.insert(stockNow);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("添加错误");
        }
        return R.ok();
    }

    @Override
    public List<BaseMaterial> getReport(String bomId, String cusCode) {
        //查出需要查询库存的 料号
        List<BaseMaterial> baseMaterialDetailsList = this.getBaseMaterialDetailsList(bomId, cusCode);
        //排除产成品
        List<String> materials = baseMaterialDetailsList.stream().filter(obj -> !obj.getClassType().equals("A")).map(BaseMaterial::getDjMaterial).collect(Collectors.toList());
        List<BaseInventory> materialInventory = baseInventoryMapper.getMaterialInventory(cusCode, materials, null);
        setInvSum(materialInventory, baseMaterialDetailsList);
        //只查询产承平
        materials = baseMaterialDetailsList.stream().filter(obj -> obj.getClassType().equals("A")).map(BaseMaterial::getDjMaterial).collect(Collectors.toList());
        materialInventory = baseInventoryMapper.getMaterialInventory(cusCode, materials, "true");
        setInvSum(materialInventory, baseMaterialDetailsList);
        return baseMaterialDetailsList;
    }

    private static void setInvSum(List<BaseInventory> materialInventory, List<BaseMaterial> baseMaterialDetailsList) {
        if (materialInventory.size() > 0){
            //计算库存总和
            Map<String, List<BaseInventory>> maps = materialInventory.stream().collect(Collectors.groupingBy(BaseInventory::getDjMaterial));
            baseMaterialDetailsList.forEach(res->{
                List<BaseInventory> baseInventories = maps.get(res.getDjMaterial());
                if (null != baseInventories){
                    //计算库存
                    double inSum = baseInventories.stream().mapToDouble(BaseInventory::getInSum).sum();
                    double outSum = baseInventories.stream().mapToDouble(BaseInventory::getOutSum).sum();
                    BigDecimal sum = new BigDecimal(inSum).subtract(BigDecimal.valueOf(outSum));
                    res.setSum(sum.longValue());
                    //计算成套数
                    if (null != res.getSum() && null != res.getBaseQty()){
                        Long baseQty = new BigDecimal(res.getBaseQty()).longValue();
                        if (baseQty > 0){
                            res.setSuitSum(res.getSum() / baseQty);
                        }
                    }
                }
            });
        }
    }

    @Override
    public List<BaseMaterial> getReportNext(String bomId, String cusCode) {
        //查询当前bom 是否存在
        List<BaseMaterial> list = baseMaterialMapper.selectList(Wrappers.lambdaQuery(BaseMaterial.class)
                .eq(BaseMaterial::getCusCode, cusCode)
                .eq(BaseMaterial::isChecked,true)
        );
        //有数据
        if (list.isEmpty()){
            return new ArrayList<>();
        }
        List<BaseMaterial> report = getReport(bomId, cusCode);
        //过滤料号
        List<String> collect = list.stream().map(BaseMaterial::getDjMaterial).collect(Collectors.toList());
        //只展示已存在表中的
        return report.stream().filter(obj -> collect.contains(obj.getDjMaterial())).collect(Collectors.toList());
    }

    public List<BaseMaterial> getMaterialNext() {
        return baseMaterialMapper.getMaterialNext();
    }
}
